package com.jack.lib.ui.widget

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Resources
import android.content.res.TypedArray
import android.graphics.Paint
import android.graphics.Typeface
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.AttributeSet
import android.view.View
import androidx.annotation.StringRes
import androidx.appcompat.widget.AppCompatTextView
import com.jack.lib.core.ext.toFloatOrDef
import com.jack.lib.ui.R

/**
 * 作者: jack(黄冲)
 * 邮箱: 907755845@qq.com
 * create on 2018/11/20 13:58
 */
@SuppressLint("AppCompatCustomView")
class JTextView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : AppCompatTextView(context, attrs, defStyleAttr) {

    var onSelectedChangeListener: ((v: View, selected: Boolean) -> Unit)? = null
    private var mHintSize = 0f
    private var textTypeface: Int = 0
    private var hintTypeface: Typeface? = null
    private var firstTextStyle: Int = 0
    private var lastTextStyle: Int = 0
    private var firstText: String? = null
    private var firstTextSize = 0f
    private var firstTextColor = 0
    private var lastText: String? = null
    private var lastTextSize = 0f
    private var lastTextColor = 0

    private object TextStyle {
        /* 粗体 */
        const val BOLD = 1

        /* 斜体 */
        const val ITALIC = 2

        /* 常规 */
        const val NORMAL = 3
    }

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.JTextView)
        parseAttr(typedArray)
        typedArray.recycle()
    }


    private fun parseAttr(typedArray: TypedArray) {

        val pLine = typedArray.getBoolean(R.styleable.JTextView_JText_P, false)
        firstText = typedArray.getString(R.styleable.JTextView_JFirstText)
        firstTextSize = typedArray.getDimension(R.styleable.JTextView_JFirstTextSize, 0f)
        firstTextColor = typedArray.getColor(R.styleable.JTextView_JFirstTextColor, 0)
        lastText = typedArray.getString(R.styleable.JTextView_JLastText)
        lastTextSize = typedArray.getDimension(R.styleable.JTextView_JLastTextSize, 0f)
        lastTextColor = typedArray.getColor(R.styleable.JTextView_JLastTextColor, 0)


        val select = typedArray.getBoolean(R.styleable.JTextView_JSelect, false)
        if (select) {
            isSelected = select
        }

        if (pLine) {
            paint.flags = Paint.UNDERLINE_TEXT_FLAG
        }
        mHintSize = typedArray.getDimension(R.styleable.JTextView_JHintSize, 0f)
        hintTypeface = getTextStyle(typedArray.getInt(R.styleable.JTextView_JHintTextStyle, 0))
        textTypeface = typedArray.getInt(R.styleable.JTextView_JTextStyle, 0)
        firstTextStyle = typedArray.getInt(R.styleable.JTextView_JFirstTextStyle, 0)
        lastTextStyle = typedArray.getInt(R.styleable.JTextView_JLastTextStyle, 0)

        if (firstText != null || lastText != null) {
            setText(getText())
        }

        val jDrawableLeft = typedArray.getDrawable(R.styleable.JTextView_JDrawableLeft)
        val jDrawableLeftWidth = typedArray.getDimension(R.styleable.JTextView_JDrawableLeftWidth, jDrawableLeft?.intrinsicWidth.toFloatOrDef(0f))
        val jDrawableLeftHeight = typedArray.getDimension(R.styleable.JTextView_JDrawableLeftHeight, jDrawableLeft?.intrinsicHeight.toFloatOrDef(0f))

        val jDrawableTop = typedArray.getDrawable(R.styleable.JTextView_JDrawableTop)
        val jDrawableTopWidth = typedArray.getDimension(R.styleable.JTextView_JDrawableTopWidth, jDrawableTop?.intrinsicWidth.toFloatOrDef(0f))
        val jDrawableTopHeight = typedArray.getDimension(R.styleable.JTextView_JDrawableTopHeight, jDrawableTop?.intrinsicHeight.toFloatOrDef(0f))

        val jDrawableRight = typedArray.getDrawable(R.styleable.JTextView_JDrawableRight)
        val jDrawableRightWidth = typedArray.getDimension(R.styleable.JTextView_JDrawableRightWidth, jDrawableRight?.intrinsicWidth.toFloatOrDef(0f))
        val jDrawableRightHeight = typedArray.getDimension(R.styleable.JTextView_JDrawableRightHeight, jDrawableRight?.intrinsicHeight.toFloatOrDef(0f))

        val jDrawableBottom = typedArray.getDrawable(R.styleable.JTextView_JDrawableBottom)
        val jDrawableBottomWidth = typedArray.getDimension(R.styleable.JTextView_JDrawableBottomWidth, jDrawableBottom?.intrinsicWidth.toFloatOrDef(0f))
        val jDrawableBottomHeight = typedArray.getDimension(R.styleable.JTextView_JDrawableBottomHeight, jDrawableBottom?.intrinsicHeight.toFloatOrDef(0f))

        jDrawableLeft?.setBounds(0, 0, jDrawableLeftWidth.toInt(), jDrawableLeftHeight.toInt())
        jDrawableTop?.setBounds(0, 0, jDrawableTopWidth.toInt(), jDrawableTopHeight.toInt())
        jDrawableRight?.setBounds(0, 0, jDrawableRightWidth.toInt(), jDrawableRightHeight.toInt())
        jDrawableBottom?.setBounds(0, 0, jDrawableBottomWidth.toInt(), jDrawableBottomHeight.toInt())

        setCompoundDrawables(jDrawableLeft, jDrawableTop, jDrawableRight, jDrawableBottom)
        compoundDrawablePadding = typedArray.getDimension(R.styleable.JTextView_JDrawablePadding, 0f).toInt()

    }


    private fun getTextStyle(style: Int): Typeface {
        return when (style) {
            Typeface.NORMAL -> Typeface.defaultFromStyle(Typeface.NORMAL)
            Typeface.BOLD -> Typeface.defaultFromStyle(Typeface.BOLD)
            Typeface.ITALIC -> Typeface.defaultFromStyle(Typeface.ITALIC)
            Typeface.BOLD_ITALIC -> Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
            else -> Typeface.defaultFromStyle(Typeface.NORMAL)
        }
    }
    override fun setPressed(pressed: Boolean) {
        super.setPressed(pressed)
        val alpha = if (pressed && isClickable) 0.8f else 1f
        if (alpha != getAlpha()) {
            setAlpha(alpha)
        }
    }

    fun text(): String {
        return text.toString()
    }

    fun text(text: CharSequence?) {
        super.setText(text)
    }

    fun firstText(text: CharSequence?) {
        val content = getText()
        firstText = text?.toString().orEmpty()
        setText(content)
    }

    fun firstText(stringRes: Int) {
        val content = context.getString(stringRes)
        firstText = context.getString(stringRes)
        text = content
    }

    fun lastText(text: CharSequence?) {
        val content = getText()
        lastText = text?.toString().orEmpty()
        setText(content)
    }

    fun lastText(stringRes: Int) {
        val content = context.getString(stringRes)
        lastText = context.getString(stringRes)
        text = content
    }

    override fun getText(): CharSequence {
        val text = super.getText()
        var s = text.toString()
        if (firstText != null) {
            s = s.replace(firstText!!, "")
        }
        if (lastText != null) {
            s = s.replace(lastText!!, "")
        }
        return s
    }

    override fun setText(text: CharSequence?, type: BufferType) {
        if (TextUtils.isEmpty(text) && hintTypeface != null) {
            paint.typeface = hintTypeface
        }
        val firstText = firstText.orEmpty()
        val lastText = lastText.orEmpty()
        val builder = SpannableStringBuilder(firstText + (text?: "") + lastText)
        if (firstText.isNotEmpty()) {
            val firstTextColor = if (firstTextColor == 0) currentTextColor else firstTextColor
            val firstTextSize = if (firstTextSize == 0f) textSize else firstTextSize
            builder.setSpan(ForegroundColorSpan(firstTextColor), 0, firstText.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            builder.setSpan(AbsoluteSizeSpan(firstTextSize.toInt(), false), 0, firstText.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            if (firstTextStyle != Typeface.NORMAL) {
                builder.setSpan(StyleSpan(firstTextStyle), 0, firstText.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            }

        }
        if (lastText.isNotEmpty()) {
            val lastTextColor = if (lastTextColor == 0) currentTextColor else lastTextColor
            val lastTextSize = if (lastTextSize == 0f) textSize else lastTextSize
            builder.setSpan(ForegroundColorSpan(lastTextColor), builder.length - lastText.length, builder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            builder.setSpan(AbsoluteSizeSpan(lastTextSize.toInt(), false), builder.length - lastText.length, builder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            if (lastTextStyle != Typeface.NORMAL) {
                builder.setSpan(StyleSpan(lastTextStyle), builder.length - lastText.length, builder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            }
        }
        builder.toString().removePrefix(firstText).removeSuffix(lastText).let {
            builder.setSpan(StyleSpan(textTypeface), firstText.length, (firstText + it).length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
        }

        super.setText(builder, type)
    }

    fun text(@StringRes resid: Int) {
        try {
            super.setText(resid)
        } catch (e: Resources.NotFoundException) {
            super.setText(resid.toString())
        }
    }

    override fun setSelected(selected: Boolean) {
        super.setSelected(selected)
        onSelectedChangeListener?.invoke(this, selected)
    }
}